package com.shanzmoo.core.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.shanzmoo.core.config.OcrProperties;
import lombok.Data;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Map;

/**
 * 阿里云OCR识别
 * @author fs
 */
@UtilityClass
@Slf4j
public class OcrUtil {
    /**
     * 银行卡识别
     * @param image
     * @return
     */
    public OcrReturn bankCardDistinguish(byte[] image){
        try{
            Dict param = Dict
                    .create()
                    .set("IMAGE_TYPE","0")
                    .set("IMAGE", imgBase64(image,"bankCard"));
            String res = ocrPost("https://cardid.market.alicloudapi.com/ai_market/ai_ocr_universal/yin_hang_ka/v1",param,"bankCard");
            if(JSONUtil.isJson(res)){
                JSONObject json = JSONUtil.parseObj(res);
                JSONObject data = json.getJSONObject("银行卡实体信息");
                String no = data.getStr("银行卡号");
                if(StrUtil.isNotBlank(no)){
                    return OcrReturn
                            .create()
                            .setFlag(true)
                            .setData(Dict
                                    .create()
                                    .set("bankNo",no)
                                    .set("bankName",data.getStr("银行名称"))
                                    .set("bankType",data.getStr("银行卡类型"))
                                    .set("bankTypeName",data.getStr("银行卡类型名称"))
                                    .set("bankValidity",data.getStr("银行卡有效期"))
                            );
                }
                return OcrReturn
                        .create()
                        .setFlag(false)
                        .setError(json.getStr("银行卡识别状态"));
            }
            return OcrReturn
                    .create()
                    .setFlag(false)
                    .setError(res);
        }catch (Exception e){
            log.error("银行卡识别异常:",e);
            return OcrReturn
                    .create()
                    .setFlag(false)
                    .setError("银行卡识别接口异常");
        }
    }

    /**
     * 身份证识别
     * @param image
     * @return
     */
    public OcrReturn idCardDistinguish(byte[] image){
        try{
            Dict param = Dict
                    .create()
                    .set("image", imgBase64(image,"idCard"));
            String res = ocrPost("https://dfidcard.market.alicloudapi.com/ocr/idcard",param,"idCard");
            if(JSONUtil.isJson(res)){
                JSONObject json = JSONUtil.parseObj(res);
                if(StrUtil.equals("OK",json.getStr("status"))){
                    JSONObject result = json.getJSONObject("result");
                    String name = result.getStr("name");
                    Dict data = Dict.create();
                    if(StrUtil.isNotBlank(name)){
                        //正面
                        data.set("address",result.getStr("address"))
                            .set("day",result.getStr("day"))
                            .set("month",result.getStr("month"))
                            .set("name",result.getStr("name"))
                            .set("nation",result.getStr("nation"))
                            .set("number",result.getStr("number"))
                            .set("sex",result.getStr("sex"))
                            .set("year",result.getStr("year"));
                    }else{
                        //反面
                        data.set("authority",result.getStr("authority"))
                            .set("timelimit",result.getStr("timelimit"));
                    }
                    return OcrReturn
                            .create()
                            .setFlag(true)
                            .setData(data);
                }
                return OcrReturn
                        .create()
                        .setFlag(false)
                        .setError(String.format("识别状态:%s", json.getStr("status")));
            }
            return OcrReturn
                    .create()
                    .setFlag(false)
                    .setError(res);
        }catch (Exception e){
            log.error("身份证识别异常:",e);
            return OcrReturn
                    .create()
                    .setFlag(false)
                    .setError("身份证识别接口异常");
        }
    }
    /**
     * 营业执照识别
     * @param image
     * @return
     */
    public OcrReturn businessLicenseDistinguish(byte[] image){
        try{
            Dict param = Dict
                    .create()
                    .set("AI_BUSINESS_LICENSE_IMAGE_TYPE", "0")
                    .set("AI_BUSINESS_LICENSE_IMAGE", imgBase64(image,"businessLicense"));
            String res = ocrPost("https://blicence.market.alicloudapi.com/ai_business_license",param,"businessLicense");
            if(JSONUtil.isJson(res)){
                JSONObject data = JSONUtil.parseObj(res);
                String nameCh = data.getStr("ENTERPRISE_NAME_CH");
                if(StrUtil.isNotBlank(nameCh)){
                    return OcrReturn
                            .create()
                            .setFlag(true)
                            .setData(Dict
                                    .create()
                                    .set("nameCh",nameCh)
                                    .set("status",data.getStr("ENTERPRISE_STATUS"))
                                    .set("registerId",data.getStr("ENTERPRISE_REGISTER_ID"))
                                    .set("id",data.getStr("ENTERPRISE_ID"))
                                    .set("registerAddress",data.getStr("ENTERPRISE_REGISTER_ADDRESS"))
                                    .set("countryId",data.getStr("ENTERPRISE_COUNTRY_ID"))
                                    .set("province",data.getStr("ENTERPRISE_PROVINCE"))
                                    .set("city",data.getStr("ENTERPRISE_CITY"))
                                    .set("district",data.getStr("ENTERPRISE_DISTRICT"))
                                    .set("bankAddress",data.getStr("ENTERPRISE_BANK_ADDRESS"))
                                    .set("tel",data.getStr("ENTERPRISE_TEL"))
                                    .set("bankName",data.getStr("ENTERPRISE_BANK_NAME"))
                                    .set("bankCountryId",data.getStr("ENTERPRISE_BANK_COUNTRY_ID"))
                                    .set("bankProvince",data.getStr("ENTERPRISE_BANK_PROVINCE"))
                                    .set("bankCity",data.getStr("ENTERPRISE_BANK_CITY"))
                                    .set("bankDistrict",data.getStr("ENTERPRISE_BANK_DISTRICT"))
                                    .set("bankId",data.getStr("ENTERPRISE_BANK_ID"))
                                    .set("owner",data.getStr("ENTERPRISE_OWNER"))
                                    .set("capital",data.getStr("ENTERPRISE_CAPITAL"))
                                    .set("time",data.getStr("ENTERPRISE_TIME"))
                                    .set("type",data.getStr("ENTERPRISE_TYPE"))
                                    .set("industry",data.getStr("ENTERPRISE_INDUSTRY"))
                                    .set("organization",data.getStr("ENTERPRISE_ORGANIZATION"))
                                    .set("usedName",data.getStr("ENTERPRISE_USED_NAME"))
                                    .set("nameEn",data.getStr("ENTERPRISE_NAME_EN"))
                                    .set("insured",data.getStr("ENTERPRISE_INSURED"))
                                    .set("people",data.getStr("ENTERPRISE_PEOPLE"))
                                    .set("scope",data.getStr("ENTERPRISE_SCOPE"))
                                    .set("validDateStart",data.getStr("ENTERPRISE_VALID_DATE_START"))
                                    .set("validDateEnd",data.getStr("ENTERPRISE_VALID_DATE_END"))
                                    .set("registerAddressCity",data.getStr("ENTERPRISE_REGISTER_ADDRESS_CITY"))
                                    .set("registerAddressDistrict",data.getStr("ENTERPRISE_REGISTER_ADDRESS_DISTRICT"))
                                    .set("registerAddressFormatAddress",data.getStr("ENTERPRISE_REGISTER_ADDRESS_FORMAT_ADDRESS"))
                                    .set("registerAddressGps",data.getStr("ENTERPRISE_REGISTER_ADDRESS_GPS"))
                                    .set("registerAddressProvince",data.getStr("ENTERPRISE_REGISTER_ADDRESS_PROVINCE"))
                                    .set("taxpayerRegisterId",data.getStr("ENTERPRISE_TAXPAYER_REGISTER_ID"))
                                    .set("universalCreditIdAgencyCode",data.getStr("ENTERPRISE_UNIVERSAL_CREDIT_ID_AGENCY_CODE"))
                            );
                }
                return OcrReturn
                        .create()
                        .setFlag(false)
                        .setError(data.getStr("ENTERPRISE_BUSINESS_CARD_OCR_STATUS"));
            }
            return OcrReturn
                    .create()
                    .setFlag(false)
                    .setError(res);
        }catch (Exception e){
            log.error("营业执照识别异常:",e);
            return OcrReturn
                    .create()
                    .setFlag(false)
                    .setError("营业执照识别接口异常");
        }
    }
    private String ocrPost(String url, Map<String,Object> param,String type){
        OcrProperties ocrProperties = SpringUtil.getBean(OcrProperties.class);
        String appCode = (String)ReflectUtil.getFieldValue(ReflectUtil.getFieldValue(ocrProperties,type),"appCode");
        HttpRequest request = HttpUtil
                .createPost(url)
                .header("Authorization", StrUtil.format("APPCODE {}",appCode));
        HttpResponse response = request.form(param).execute();
        String res = response.body();
        return res;
    }
    private String imgBase64(byte[] image,String type){
        if(StrUtil.equals("bankCard",type)){
            //银行卡 400*400
            //100KB以上缩放图片为长宽为400的小图片
            if(image.length>100*1024){
                image = scale(image,400,400);
            }
        }else if(StrUtil.equals("idCard",type)){
            //身份证 400*400
            //100KB以上缩放图片为长宽为400的小图片
            if(image.length>100*1024){
                image = scale(image,400,400);
            }
        }else if(StrUtil.equals("businessLicense",type)){
            //营业执照 1600*1600
            //2MB以上缩放图片为长宽为1600的小图片
            if(image.length>2*1024*1024){
                image = scale(image,1600,1600);
            }
        }
        return Base64.encode(image);
    }
    /**
     * 图片缩放
     * @param image 图片
     * @return
     */
    private byte[] scale(byte[] image,int width,int height){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImgUtil.scale(new ByteArrayInputStream(image),baos,width,height,null);
        byte[] tmpImg = baos.toByteArray();
        return tmpImg;
    }
    @Data
    public static class OcrReturn{
        private Boolean flag;
        private String error;
        private Dict data;
        public static OcrReturn create(){
            return new OcrReturn();
        }
        public OcrReturn setFlag(boolean flag){
            this.flag = flag;
            return this;
        }
        public OcrReturn setError(String error){
            this.error = error;
            return this;
        }
        public OcrReturn setData(Dict data){
            this.data = data;
            return this;
        }
        @Override
        public String toString(){
            return JSONUtil.toJsonStr(this);
        }
    }

}
